
#ifndef __PAISLEYPARK__MULTIGRIDSOLVERFACTORY_H__
#define __PAISLEYPARK__MULTIGRIDSOLVERFACTORY_H_

#include "MultigridSolver.h"
#include "map"
#include "cstring"

template <size_t DIM>
class MultigridSolverFactory {
public:
	typedef MultigridSolver<DIM>* (*CreateMethodCallback)(std::string s1, std::string s2);
private:
	typedef std::map<std::string, CreateMethodCallback> CallbackMp;
public:

	bool RegisterMethod(const std::string _MethodId, CreateMethodCallback _createFn);

	bool UnregisterMethod(const std::string _MethodId);

	MultigridSolver<DIM>* CreateMethod(const std::string _MethodId, std::string s1, std::string s2);

	~MultigridSolverFactory(){};

	static MultigridSolverFactory<DIM>* Instance() {
		if(!__obj) {
			__obj = new MultigridSolverFactory<DIM>;
		}
		return __obj;
	} 
private:
	static MultigridSolverFactory<DIM>* __obj;

	CallbackMp __callbacks;

	MultigridSolverFactory(){};
};

template <size_t DIM>
MultigridSolverFactory<DIM>* MultigridSolverFactory<DIM>::__obj = 0;

template <size_t DIM>
bool MultigridSolverFactory<DIM>::RegisterMethod(const std::string _MethodId,
												 CreateMethodCallback _createFn) {
	return __callbacks.insert(typename CallbackMp::value_type(_MethodId, _createFn)).second;
};

template <size_t DIM>
bool MultigridSolverFactory<DIM>::UnregisterMethod(const std::string _OperatorId) {
	return __callbacks.erase(_OperatorId) == 1;
}

template <size_t DIM>
MultigridSolver<DIM>* MultigridSolverFactory<DIM>::CreateMethod(const std::string _MethodId, std::string s1, std::string s2) {
	typename CallbackMp::const_iterator i = __callbacks.find(_MethodId);
	if(i == __callbacks.end()) {
		std::cerr << "Unknown Method Id." << std::endl;
		std::exit(-1);
	}
	return (i->second)(s1, s2);
}

#else
//Do nothing.
#endif
